03. 웹 사이트 성능을 개선하는 기본적인 방법
📝 Contents
HTTP 요청 수 줄이기
- 웹 사이트는 수많은 이미지와 멀티미디어, 웹 사이트의 독자적 기능을 수행하기 위한 자바스크립트, UI 및 레이아웃을 위한 CSS, 웹 폰트, 음원 파일 등으로 뒤덮여 있음
- 웹 페이지에서 요청하는 콘텐츠의 수가 많을수록 로딩 완료 시간은 길어짐
- 일반적으로 브라우저는 DNS 시스템으로 특정 도메인의 접속 IP를 알아내 접속을 하고, HTML 파일을 먼저 응답받은 후 HTML 내에 있는 CSS나 자바스크립트, 이미지 등의 콘텐츠를 차례로 호출함
- HTML을 받아온 도메인과 콘텐츠 주소가 다르면 DNS 조회부터 다시 수행함
- 웹 페이지를 단순하게 제작하는 것이 HTTP 프로토콜 요청 수를 줄이는 가장 쉬운 방법임
- 하지만 웹 성능을 위해 나타낼 콘텐츠를 줄이는 것이 현실적으로 적절한 방법은 아님
- 페이지에 나타나는 콘텐츠는 동일하게 유지하며 HTTP 요청 수를 줄이는 방법을 찾아야 함
스크립트 파일 병합
- 소프트웨어 공학에서는 소프트웨어 개발의 손쉬운 분업화 및 편리한 유지 보수를 위해 최소 기능 단위별로 소프트웨어 모듈을 나누어 개발하는 것을 제안하는데 이를 모듈화라고 함
- 웹 개발에서도 이 방식을 많이 사용
- 하지만 모듈화는 HTTP 요청 수를 증가시키므로 웹 성능에 부정적인 영향을 미침
- 파일 병합으로 HTTP 요청 수를 줄일 수 있음
- 그러나 합쳐진 파일의 크기가 너무 크다면 그 파일을 다운로드해 브라우저 화면에 나타내는 로딩 과정이 너무 길어질 수 있으므로 적절한 크기를 유지해야함
- 자바스크립트나 CSS같은 텍스트 기반 파일에 적용되는 내용임
인라인 이미지
- HTML 파일의 CSS 안에 해시 정보를 통해 웹 페이지 배경 이미지 파일을 삽입하는 방식
- 이 방식을 사용하면 HTML 파일의 바이트 크기가 소폭 커짐
- 하지만 이미지 파일을 따로 호출하여 해당 크기만큼 파일을 받아오는 전통적인 방식과 비교하면 전체 로딩 시간이 단축됨
- 인라인 방식으로 웹 페이지 안에 이미지를 포함하는 경우 별도의 이미지 파일이 존재하지 않아 인터넷이나 브라우저에 캐시할 수 없으며, HTML이 캐시되어야 동시에 캐시할 수 있음
- 그러므로 전반적인 성능 개선 여부를 확인하고 선택 사용해야 함
- 파일을 병합하는 방법은 HTTP 요청 수를 줄이는 효과 외에도 인터넷상 프록시나 브라우저에 캐시될 확률을 좀 더 높임
CSS 스프라이트
- 여러 개의 이미지를 하나의 이미지 파일로 결합해 필요한 이미지가 위치하는 픽셀 좌표 정보를 사용하는 방식
- 주로 아이콘이나 버튼 등 작은 이미지를 사용할 때 유용하며 HTML에 필요한 이미지 영역을 이미지 맵 좌표로 표시함
콘텐츠 파일 크기 줄이기
- 웹 사이트의 파일 수를 줄이더라도 파일 자체의 크기가 크다면 이 또한 웹 성능에 부정적인 영향을 줌
- 보다 빠른 웹을 위해 사이트 내 다양한 콘텐츠 파일의 크기를 줄여야 하지만 파일 내용은 변하면 안됨
- 파일 내용은 변하지 않고 크기를 줄일 수 있는 기능들이 있음
스크립트 파일 압축 전달
- 각 웹 서버가 지원하는 방식으로 스크립트 형태 콘텐츠를 압축해 클라이언트에게 더 작은 크기로 내려주고, 이를 다운로드한 클라이언트가 압축을 해제하여 원래 콘텐츠를 사용한다면 인터넷 다운로드 속도가 좀 더 빨라질 수 있음
- 파일을 압축하여 내려주기 전에 웹 서버와 클라이언트는 서로가 지원하는 다양한 압축 방식 중 어떤 것을 사용할지 하나를 골라 정해야 함
- 클라이언트는 HTTP 요청 헤더에 Accept-Encoding을 사용하여 자신이 지원하는 압축 알고리즘을 알려줌
Accept-Encoding: gzip, deflate, sdch
- 웹 서버는 HTTP 응답 헤더에 Content-Encoding을 사용하여 자신이 지원하는 압축 알고리즘 하나를 선택해 알려줌
- 각 압축 방식을 간단히 설명하면 다음과 같음
- gzip: UNIX 운영체제에서 일반적으로 사용하는 LZ77 파일 압축 라이브러리를 사용함. 32비트 CRC로 정상 압축 여부를 검사함
- deflate: zlib라는 파일 압축 라이브러리를 사용함. RFC 1951에 정의된 압축 방식임
- sdch(Shared Dictionary Compression over HTTP): 구글이 개발한 HTTP 상의 압축 방식임. 주로 크롬 브라우저에서 사용함
스크립트 파일 최소화
- HTML, 자바스크립트, CSS 같이 코딩된 스크립트 파일에 포함된 주석문, 공백, 개행 문자 등 실제 로직에 아무런 영향을 주지 않는 부분을 제거하여 전반적인 파일 크기를 줄이는 방식
- Minify 사이트에서 스크립트 파일 최소화 기법으로 파일 크기를 얼마나 줄일 수 있는지 알 수 있음
- 해당 사이트의 로직을 변경해야 하거나 버그를 디버깅 하는 등 개발자의 작업이 필요한 경우 최소화된 파일로는 불가능 할 수 있음
- 따라서 개발 서버와 운영 서버를 분리하는 방법을 많이 이용함
- 개발자들이 개발 서버에서 스크립트 원본 파일을 두고 개발하고, 로직 테스트와 검증 작업이 완료되면 이 스크립트를 최소화해 운영 서버로 이관하여 운영 시에만 최소화된 스크립트 파일을 사용하는 방식
- 가장 효과적인 방법은 스크립트 파일 최소화로 불필요한 부분을 제거해 파일을 가볍게 만든 후, gzip 등의 압축 방식으로 서버가 내려준 파일을 클라이언트가 압축 해제하는 두 방법을 모두 사용하는 것임
이미지 파일 압축
- 이미지 파일은 해당 파일 정보를 메타 데이터에 포함해 저장함
- 메타 데이터는 사람 눈에 실제 이미지로써 보이지 않으므로 불필요한 부분을 제거하면 크기를 상당히 줄일 수 있음
- tiny png의 온라인 서비스를 이용하면 손실 압축 방식으로 이미지 파일을 압축할 수 있음
브라우저가 선호하는 이미지 포맷 사용
- 웹상의 이미지는 JPG, GIF, PNG, BMP 등 다양한 포맷을 사용함
- 동일 품질의 이미지 크기를 더욱 줄일 수 있는 이미지 포맷이 개발됬는데, 구글의 크롬은 WebP, 마이크로소프트의 익스플로러는 JPEG XR
- WebP는 손실 압축 방식을 사용하는 이미지 형식
- JPEG 형식을 대체하기 위해 처음부터 웹 사이트 트래픽 감소, 로딩 속도 단축을 목적으로 개발
- 품질은 JPEG와 거의 동일하지만, 평균 50% 정도 파일 크기가 작아짐
- JPEG XR은 JPEG 형식에 장점을 추가해 개발한 이미지 압축 형식
- 손실 압축과 비손실 압축 방식을 모두 지원함
- 웹에서 평균적으로 JPEG의 30% 정도 크기로 동일한 품질의 이미지를 표시할 수 있음
큰 파일은 작게 나누어 전송
- 크기가 큰 파일은 일부분을 순서대로 다운로드하는 부분 요청 응답 방식을 사용할 수 있음
- 부분 요청 응답 방식은 웹 서버에 특정 부분 파일 전달을 지원하는 기능이 있을 때만 사용할 수 있음
- 이 기능은 웹 서버의 응답 헤더를 통해 확인할 수 있음
// 웹 서버의 부분 응답 지원 여부 확인
curl -I http://www.example.com/bigfile.jpg
HTTP/1.1 200 ok
(중략)
Accept-Ranges: bytes // byte 단위로 파일의 부분(Ranges) 지원 기능을 수락(Accept) 한다는 의미
Content-Length: 50000000 // 해당 파일의 전체 크기가 50MB라는 정보를 클라이언트에게 알려줌
(중략)
- 웹 서버가 부분 파일 지원 기능을 명시하면 클라이언트는 특정 부분만 요청 가능
// 파일의 특정 부분 요청하기
curl -V http://www.example.com/bigfile.jpg -H "Range: bytes=0-1023" // 전체 파일이 아닌 처음(0)부터 1023바이트까지의 파일만 요청
- 웹 서버는 206 Partial Content 응답으로 자신이 전체 파일 중 부분만 전달했음을 명시
// 웹 서버의 206 응답
HTTP/1.1 206 Partial Content
Content-Range: bytes 0-1023/50000000 // 전체 파일 범위 중 처음부터 1023바이트까지만 전달한다는 의미
Content-Length: 1024 // 현재 전달한 부분 파일의 전체 용량이 시작 위치와 끝 위치를 알려주는 데이터를 포함하여 1024임을 명시함. 부분 파일의 마지막임을 알려주는 지시자가 포함되어 1023보다 큼
(생략)
(실제 파일의 해당 부분 콘텐츠)
- 긴 영상을 재생할 때 동영상 플레이어에 보이는 조정 바는 이 값을 이용해 제작함
- 부분 파일을 요청할 때 여러 범위 파일을 쉼표(,)를 사용해 동시 요청할 수 있는데, 특정 부분의 영상을 재생하면서 뒷부분 영상을 살짝 드러내고 싶을때 유용함
// 여러 범위를 가진 부분 파일 요청
curl -V http://www.example.com/bigfile.jpg -H "Range: bytes=0-50, 100-150"
캐시 최적화하기
- IT 분야에서 캐시는 자주 사용되는 콘텐츠나 특정 데이터 등을 임의로 저장소에 복제해두고 재사용하는 방식
- 인터넷상에서 캐시는 ISP 회사가 지역에 분포된 특정 시스템에 사용자와 원격 시스템 사이에서 주고받은 데이터를 캐시하고 다음 사용자에게 제공하는 방식으로 널리 사용됨
- 콘텐츠를 캐시하는 시스템을 프록시(proxy)서버라고 부름
- 인터넷 캐시는 캐시 영역에 미리 데이터를 복사해 두는 PUSH 방식과 실제 요청이 있을 때만 캐시에 저장하는 PULL 방식으로 분류
- PUSH 방식은 특정 시간, 특정 지역에 사용자의 요청이 과다하게 몰릴 것에 대비할 수 있음
- 인터넷 캐시가 발달하자 해당 콘텐츠를 소모하는 브라우저도 콘텐츠를 캐시하기 시작
- 자주 바뀌지 않는 이미지나 자바스크립트, CSS 파일 등을 인터넷 프록시 서버에도 캐시하지만 사용자의 브라우저도 해당 기기에 캐시함
인터넷 캐시 사용
- 인터넷상에서 자주 요청되는 콘텐츠를 캐시하는 것은 속도와 인프라 보호 차원에서 중요함
- 이를 주로 담당하는 시스템은 프록시 서버로 인터넷의 수많은 경로에 거미줄같이 존재함
- 프록시라는 단어는 본래 대리인을 뜻하는데, 서버 대신 클라이언트의 지원 요청에 응답해주는 본연의 기능에서 유래됨
- 일반적으로 콘텐츠 소비자와 제공자 사이의 인터넷 구간이 멀 때 구간의 중간 정도에 하드웨어 또는 소프트웨어 방식으로 프록시를 설치해 사용함
- 서버와 클라이언트 사이에서 통신을 대신하는 기능 자체를 프록시, 그 중계 기능을 수행하는 서버를 프록시 서버라고 함
- 프록시 서버는 클라이언트가 처음 요청한 콘텐츠를 원본 서버에 대신 요청하여 클라이언트에 전달해주고 이를 스스로 저장함
- 이후 다른 클라이언트가 동일한 콘텐츠를 요청했을 때 원본 서버에 접속할 필요 없이 자체 저장한 콘텐츠를 제공함
- 이 방식은 두 가지 장점이 있음
- 사용자 부근의 프록시 서버의 응답 속도가 원래 서버의 응답 속도보다 빠름
- 원본 서버로 몰릴 수 있는 인터넷 트래픽을 프록시 서버로 분산해 원본 서버의 자원을 절약함
브라우저 캐시 사용
- 브라우저 캐시는 클라이언트 위치의 캐시
- 특정 웹 사이트에 접속하여 받아온 웹 콘텐츠들 중 브라우저가 저장할 수 있는 콘텐츠들을 클라이언트 측에 저장해 인터넷상의 요청을 아예 하지 않겠다는 개념
- 특정 콘텐츠가 브라우저 캐시를 사용할지 아닐지는 일반적으로 웹 서버에서 먼저 결정해야 함
- 따라서 웹 서버 관리자는 관련 인원들과 해당 콘텐츠의 캐시 정책을 조사하고 이를 웹 서버의 캐시 설정에 충실히 적용해야 함
- 특정 콘텐츠를 브라우저에서 캐시할 수 있게 하고, 얼마나 긴 시간 동안 캐시해도 되는지 정책이 결정되면 웹 서버는 Cache-Control 응답 헤더를 통해 설정 내용을 클라이언트에게 전달
- 이에 대한 자세한 예제는 책 3.3.2절 참고
CDN 사용하기
- CDN(Content Delivery Network, 콘텐츠 전송 네트워크)은 인터넷상에서 생산-소비되는 웹 콘텐츠를 사용자에게 빠르게 전달하기 위해 캐시 서버(cache server) 혹은 엣지 서버끼리 HTTP가 아니라 ICP로 통신하는 이유(edge server)라 불리는 대용량 인터넷 캐시 영역에 콘텐츠를 저장해 사용하는 네트워크 방식
- 여러 노드를 가진 네트워크에 콘텐츠를 저장하여 제공하는 프록시의 일종으로 ICP(Internet Cache Protocol)은 오늘날 인터넷 환경에서 광범위하게 사용되어 전 세계 인터넷 트래픽 성능을 개선해줌
- CDN은 주로 실제 인터넷 사용자가 가입한 ISP의 데이터 센서 내에 캐시 서버를 두고 이를 직접 사용자와 연결해 데이터를 전송함
- CDN을 사용하면 다음과 같은 장점이 있음
- 인터넷상 원거리에 있는 콘텐츠를 전달받는 과정에서 클라이언트와 웹 서버 사이에 발생할 수 있는 네트워크 지연과 패킷 손실 현상을 줄일 수 있음
- 사용자는 가까운 엣지 서버끼리 HTTP가 아니라 ICP로 통신하는 이유에 캐시된 콘텐츠를 전달받으므로 전송에 필요한 RTT가 줄어들어 빠르게 콘텐츠를 받을 수 있음
- CDN의 엣지 서버끼리 HTTP가 아니라 ICP로 통신하는 이유가 캐시된 ICP(Internet Cache Protocol)은 콘텐츠를 전송하므로 원본 서버의 부하를 줄일 수 있음. 또한 인프라를 확충하는 데 드는 인력과 경비를 줄일 수 있음
- 콘텐츠가 엣지 서버끼리 HTTP가 아니라 ICP로 통신하는 ICP(Internet Cache Protocol)은 이유와 주변 엣지 서버끼리 HTTP가 아니라 ICP로 통신하는 이유 사이에 ICP를 이용한 서버 전파를 할 수 있어 캐시 콘텐츠의 재사용률이 매우 높음
- CDN 사업자들은 사용자 요청 트래픽이나 기술적 특이 사항을 ICP(Internet Cache Protocol)은 모니터링하는 시스템을 갖추고 있어 인터넷 전송이 필요한 ICP(Internet Cache Protocol)은 콘텐츠의 시스템과 인적 관리 비용이 절감됨
- 최근 콘텐츠와 시스템이 데이터 센터에서 클라우드로 이동하는 추세임
- 따라서 인터넷상에서 콘텐츠를 전달할 때 발생할 수 있는 문제점을 개선하거나 성능을 유지하고 관리해야 하는 새로운 가속화 과제가 등장하고 있음
- 이러한 과제를 해결하려는 CDN 기술도 진보하고 있음
💭 Insights
이미지 파일 압축 - 손실 압축과 비손실 압축
- 책에서 이미지 파일은 압축해서 사용하면 좋다고 나온다.
- 여태 나는 압축을 해놓으면 압축을 해제해야 사용 가능하다고 생각했었다.
- 불필요한 부분을 제거하는 것이 손실 압축이라는데 손실 압축은 압축된 상태에서도 사용이 가능한 것인가?
- 찾아보니까 PNG같은 경우는 비손실 압축이라는 데 비손실 압축을 해도 압축 해제 없이 사용 가능한 것인가?
- 그리고 모든 JPEG는 손실 압축, PNG는 비손실 압축이라고 나오는데, 그럼 애초에 모든 이미지들이 다 압축이 된 상태인건가?
- 책에 나온 tiny png에서 png를 압축해 보니 zip 파일로 압축이 되고 해제시 용량이 작아져있는거 보니 손실 압축이 맞긴 한거 같은데 png도 그럼 손실 압축이 되는거 같은데 왜 비손실 압축인건지 궁금하다.
- 이미지 파일은 일반적으로 JPEG, PNG, WebP 모두 압축이 된 형태인 것 같다.
- 또한 압축된 파일을 꼭 풀어서 사용하는 것이 아니라 이미지는 그냥 보여지는 것 같다.
- 책에서 말한 이미지 압축하기는 확장자로 압축된 것과 별개로, 어떤 확장자의 파일이든 한 번 더 손실 압축으로 압축해서 사용하면 좋다는 의미인 것 같다.
이미지 포맷 종류와 차이점
- JPEG: 손실 압축, 이미지 파일을 압축하면 보통 이미지 질이 떨어지는데, JPEG는 이미지 손상 없이 이미지를 압축해서 가장 많이 활용됨. 주로 사진에 많이 사용
- PNG: 비손실 압축, 이미지 디테일 손실이 전혀 없고, JPEG 형식보다 더 고품질 이미지를 생성하지만 파일 크기는 JPEG에 비해 더 커짐. 주로 로고나 고품질 이미지에 많이 사용
- WebP: 손실/비손실 압축, 웹에 최적화 되어 있임. JPEG 대비 파일 크기 25~50% 감소, PNG와 유사한 비손실 품질. 웹에 사용되는 사진, 로고에 많이 사용
- GIF: 비손실 압축, 8비트 컬러 팔레트를 사용하여 최대 256가지 색상만 지원함. 애니메이션을 지원하고 파일 크기가 작음. 단순 그래픽에서 좋음.
엣지 서버끼리 HTTP가 아니라 ICP로 통신하는 이유
- ICP(Internet Cache Protocol)는 캐시 서버 간의 간단한 요청/응답(HIT/MISS)을 처리하기 위해 설계됨
- 추가적인 상태 정보나 메타데이터 없이, 단순한 메시지 구조로 빠르게 작동함
- ICP는 TCP가 아닌 UDP 기반이라 연결 설정 과정이 없으며, 작은 패킷을 빠르게 주고받기에 적합함
- HTTP는 캐시 서버 간 협력에 과도한 리소스를 사용할 수 있지만, ICP는 가볍고 빠르기 때문에 서버 간 부하를 최소화함